package com.calvin.study.completablefuture;

import java.math.BigDecimal;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;

import org.apache.commons.lang3.StringUtils;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.RandomUtil;

public class WhenCompleteTest extends BaseThreadPoolExecutor {
	
	public static void main(String[] args) {
		try {
			System.out.println("main ... start");
			//whenCompleteTest();
			handleTest();
			
			System.out.println("main ... end");
		} catch (Exception e) {
			// TODO: handle exception
		}

	}
	
	public static void whenCompleteTest() throws InterruptedException, ExecutionException {
		CompletableFuture<String> cf = CompletableFuture.supplyAsync(()->{
			//生成订单（伪代码）
			String orderId = new Snowflake().nextIdStr();
			BigDecimal price = RandomUtil.randomBigDecimal(new BigDecimal(10), new BigDecimal(101));
			int count = RandomUtil.randomInt(1, 21);
			BigDecimal totalPrice = price.multiply(new BigDecimal(count));// 总价

			// 业务执行成功返回值
			return orderId + "$" + price + "$" + count + "$" + totalPrice;
		}, executor)
		.whenCompleteAsync(new BiConsumer<String, Throwable>(){
			@Override
			public void accept(String res, Throwable exception) {
				//能得到异常信息，accept方法无返回值，所以没法修改返回数据
				//订单日志（伪代码）
				System.out.println("插入订单日志：" + res);
			}
		}, executor);
//		.exceptionally(throwable-> {
//			//可以感知异常，同时返回值
//			//业务执行异常返回值
//			return 9999;
//		});
		
		System.out.println(cf.get());
	}
	
	public static void handleTest() throws InterruptedException, ExecutionException {
		//方法执行完成后的处理
		CompletableFuture<String> cf = CompletableFuture.supplyAsync(()->{
			//生成订单（伪代码）
			String orderId = new Snowflake().nextIdStr();
			BigDecimal price = RandomUtil.randomBigDecimal(new BigDecimal(10), new BigDecimal(101));
			int count = RandomUtil.randomInt(1, 21);
			BigDecimal totalPrice = price.multiply(new BigDecimal(count));// 总价
			int i = 10/0;
			// 业务执行成功返回值
			return orderId + "$" + price + "$" + count + "$" + totalPrice;
		}, executor).handleAsync(new BiFunction<String, Throwable, String>() {
			
			@Override
			public String apply(String res, Throwable exception) {
				if(StringUtils.isNotBlank(res)) {
					System.out.println("插入订单日志：" + res);
					return "0000";
				}
				if(null!=exception) {
					System.out.println("订单生成失败，执行补偿机制");
					return "9999";
				}
				return "9999";
			}
			
		}, executor).exceptionally(new Function<Throwable, String>() {
			@Override
			public String apply(Throwable t) {
				if(null!=t) {
					if (t instanceof CompletionException) {
						System.out.println("订单数据计算异常：" + t.getMessage());
					}
				}
				return "9999";
			}
		});
		
		System.out.println(cf.get());
	}

}
